/*
 * SymbianSDKSensors.cpp
 *
 *  Created on: 22.12.2009
 *      Author: Anssi
 */

#define CRITERIA_ACCELEROMETERAXIS "AccelerometerAxis" 	
#define CRITERIA_ACCELEROMETERDOUBLETAPPING "AccelerometerDoubleTapping"
#define CRITERIA_ACCELEROMETERORIENTATION "Orientation"
#define CRITERIA_ACCELEROMETERROTATION "Rotation"
#define CRITERIA_ACCELEROMETERALL "All"

#define ERR_CODE_OK 0 //Success
#define ERR_CODE_INVALID_SERVICE_ARGUMENT 1000 //Invalid service argument
#define ERR_CODE_UNKNOWN_ARGUMENT_NAME 1001 //Unknown argument name
#define ERR_CODE_BAD_ARGUMENT_TYPE 1002 //Bad argument type
#define ERR_CODE_MISSING_ARGUMENT 1003 //Missing argument 
#define ERR_CODE_SERVICE_NOT_SUPPORTED 1004 //Service not supported
#define ERR_CODE_SERVICE_IN_USE 1005 //Service in use
#define ERR_CODE_SERVICE_NOT_READY 1006 //Service not ready
#define ERR_CODE_NO_MEMORY 1007 // No memory
#define ERR_CODE_HARDWARE_NOT_AVAILABLE 1008 //Hardware not available
#define ERR_CODE_SERVER_BUSY 1009 // Server busy
#define ERR_CODE_ENTRY_EXISTS 1010 // Entry exists
#define ERR_CODE_ACCEESS_DENIED 1011 // Access denied
#define ERR_CODE_NOT_FOUND 1012 // Not found
#define ERR_CODE_UNKNOWN_FORMAT 1013 // Unknown format
#define ERR_CODE_GENERAL_ERROR 1014 // General error
#define ERR_CODE_CANCEL_SUCCESS 1015 // Cancel success
#define ERR_CODE_SERVICE_TIMED_OUT 1016 // Service timed-out
#define ERR_CODE_PATH_NOT_FOUND 1017 // Path not found

#include <QString>
#include <QDebug>

#include "SymbianSDKSensors.h"
#include "sensordatalistener.h"

#include <sensrvchannelfinder.h> 
#include <sensrvaccelerometersensor.h> 
#include <sensrvtappingsensor.h> 
#include <sensrvorientationsensor.h> 
#include <sensrvchannel.h>
#include <e32base.h> 

SymbianSDKSensors::SymbianSDKSensors(Sensors &sensors) : m_sensors(sensors), m_transactionID(0x100)
	{
	// TODO Auto-generated constructor stub

	}

SymbianSDKSensors::~SymbianSDKSensors()
	{
	// TODO Auto-generated destructor stub
	}

void SymbianSDKSensors::findSensorChannel(const QString &criteria)
{
	// criteria options: "All", "AccelerometerAxis", "AccelerometerDoubleTapping", 
	// "Orientation", "Rotation"
	int ChannelId = 0, 
	ContextType = 0, 
	Quantity = 0, 
	ChannelType = 0, 
	DataItemSize = 0, 
	ChannelDataTypeId = 0;
        //QString location("");
        //QString VendorId("");


	CSensrvChannelFinder* SensrvChannelFinder = CSensrvChannelFinder::NewLC();  
	RSensrvChannelInfoList ChannelInfoList; 
	CleanupClosePushL( ChannelInfoList );  
	TSensrvChannelInfo mySearchConditions;
	// none, so matches all. 
	SensrvChannelFinder->FindChannelsL(ChannelInfoList,mySearchConditions);  
	// do something with the ChannelInfoList  ChannelInfoList.Close(); 
	CleanupStack::Pop( &ChannelInfoList ); 
	CleanupStack::PopAndDestroy( SensrvChannelFinder );

	for ( TInt i = 0; i < ChannelInfoList.Count() ; i++ ) 
		{ 	
                        ChannelId = ChannelInfoList[i].iChannelId;
			ContextType = ChannelInfoList[i].iContextType;
			Quantity = ChannelInfoList[i].iQuantity;
                        ChannelType = ChannelInfoList[i].iChannelType;
			DataItemSize = ChannelInfoList[i].iDataItemSize;
			ChannelDataTypeId = ChannelInfoList[i].iChannelDataTypeId;

                        TBuf16<KSensrvLocationLength> Location16;
                        TBuf16<KSensrvVendorIdLength> VendorId16;
                        Location16.Copy(ChannelInfoList[i].iLocation);
                        VendorId16.Copy(ChannelInfoList[i].iVendorId);

                        QString location = QString((QChar*)(Location16.Ptr()), Location16.Length());//QString::fromRawData(reinterpret_cast<const QChar*>(ChannelInfoList[i].iLocation.Ptr()), ChannelInfoList[i].iLocation.Length());
                        QString VendorId = QString((QChar*)(VendorId16.Ptr()), VendorId16.Length()); //QString::fromRawData(reinterpret_cast<const QChar*>(ChannelInfoList[i].iVendorId.Ptr()), ChannelInfoList[i].iVendorId.Length());

			if(criteria == CRITERIA_ACCELEROMETERAXIS && ChannelInfoList[i].iChannelType == KSensrvChannelTypeIdAccelerometerXYZAxisData) 	
			{
                            // ChannelId, ContextType, Quantity, ChannelType, location, VendorId, DataItemSize, ChannelDataTypeId
                            m_sensors.addChannelInfo(ChannelId, ContextType, Quantity, ChannelType, location, VendorId, DataItemSize, ChannelDataTypeId);
			}
			else if(criteria == CRITERIA_ACCELEROMETERDOUBLETAPPING && ChannelInfoList[i].iChannelType == KSensrvChannelTypeIdAccelerometerDoubleTappingData)
			{
                            m_sensors.addChannelInfo(ChannelId, ContextType, Quantity, ChannelType, location, VendorId, DataItemSize, ChannelDataTypeId);
			}
			else if(criteria == CRITERIA_ACCELEROMETERORIENTATION && ChannelInfoList[i].iChannelType == KSensrvChannelTypeIdOrientationData)
			{
                            m_sensors.addChannelInfo(ChannelId, ContextType, Quantity, ChannelType, location, VendorId, DataItemSize, ChannelDataTypeId);
			}
                        else if(criteria == CRITERIA_ACCELEROMETERROTATION && ChannelInfoList[i].iChannelType == KSensrvChannelTypeIdRotationData)
			{
                            m_sensors.addChannelInfo(ChannelId, ContextType, Quantity, ChannelType, location, VendorId, DataItemSize, ChannelDataTypeId);
			}
			else if(criteria == CRITERIA_ACCELEROMETERALL)
			{
                            m_sensors.addChannelInfo(ChannelId, ContextType, Quantity, ChannelType, location, VendorId, DataItemSize, ChannelDataTypeId);
			}
		}
}

int SymbianSDKSensors::registerForNotification(int ChannelId, int ContextType, int Quantity, int ChannelType, const QString &location, const QString &VendorId, int DataItemSize, int ChannelDataTypeId)
{
	TSensrvChannelInfo info;
	info.iChannelId = ChannelId;
	info.iContextType = ContextType;
	info.iQuantity = Quantity;
	info.iChannelType = ChannelType;
	TPtrC locationDescriptor(static_cast<const TUint16*>(location.utf16()), location.length());
	info.iLocation.Append(locationDescriptor);
	TPtrC vendorIdDescriptor(static_cast<const TUint16*>(VendorId.utf16()), VendorId.length());
	info.iVendorId.Append(vendorIdDescriptor);
	info.iDataItemSize = DataItemSize; 
	info.iChannelDataTypeId = ChannelDataTypeId;

    CSensrvChannelFinder* finder = CSensrvChannelFinder::NewLC();
    RSensrvChannelInfoList channelList;
    CleanupClosePushL(channelList);
    finder->FindChannelsL(channelList, info);

    if (channelList.Count() > 0)
        {
        m_transactionID++;
        info = channelList[0];

        CSensrvChannel *aChannel = CSensrvChannel::NewL(info);
        CSensorDataListener *listener = new CSensorDataListener(m_transactionID, m_sensors);
        aChannel->OpenChannelL();
        m_transactions.insert(m_transactionID, new TransactionObject(aChannel, listener));
        aChannel->StartDataListeningL(listener, 1, 1, 0);
        }
    channelList.Close();
    CleanupStack::Pop( &channelList );
    CleanupStack::PopAndDestroy( finder );
    
    return m_transactionID;
}

void SymbianSDKSensors::cancel(int criteria)
	{
		if(m_transactions.contains(criteria)) {
			TransactionObject *transactionToCancel = m_transactions[criteria];
			transactionToCancel->m_channel->StopDataListening();
			transactionToCancel->m_channel->CloseChannel();
			delete transactionToCancel;
		}
	}

void SymbianSDKSensors::getChannelProperty(const QString &listeningType, int ChannelId, int ContextType, int Quantity, int ChannelType, const QString &location, const QString &VendorId, int DataItemSize, int ChannelDataTypeId, const QString &PropertyId)
{
	TSensrvChannelInfo info;
	info.iChannelId = ChannelId;
	info.iContextType = ContextType;
	info.iQuantity = Quantity;
	info.iChannelType = ChannelType;
	TPtrC locationDescriptor(static_cast<const TUint16*>(location.utf16()), location.length());
	info.iLocation.Append(locationDescriptor);
	TPtrC vendorIdDescriptor(static_cast<const TUint16*>(VendorId.utf16()), VendorId.length());
	info.iVendorId.Append(vendorIdDescriptor);
	info.iDataItemSize = DataItemSize; 
	info.iChannelDataTypeId = ChannelDataTypeId;
	
	CSensrvChannelFinder* finder = CSensrvChannelFinder::NewLC();
	RSensrvChannelInfoList channelList;
	CleanupClosePushL(channelList);
	finder->FindChannelsL(channelList, info);
	
	if (channelList.Count() > 0)
	{
		RSensrvPropertyList propertyList;
		info = channelList[0];
		CSensrvChannel *aChannel = CSensrvChannel::NewL(info);
		aChannel->GetAllPropertiesL(propertyList);
		delete aChannel;
		if(propertyList.Count() > 0)
		{
			//propertyList[0].GetPropertyId()
			QString PropertyId(QString::number(propertyList[0].GetPropertyId()));
			int PropertyDataType =  propertyList[0].PropertyType();
			int ItemIndex = propertyList[0].GetArrayIndex();
			bool ReadOnly =  propertyList[0].ReadOnly();
		
			//m_sensors.relayChannelProperties(PropertyId, PropertyDataType, ItemIndex, ReadOnly, PropertyValue);
		}
	}
	channelList.Close();
	CleanupStack::Pop( &channelList );
	CleanupStack::PopAndDestroy( finder );
}
